package cn.openea.perpartner.meily.web.service.impl;

import cn.openea.perpartner.common.core.exception.ServiceException;
import cn.openea.perpartner.meily.web.entity.CourseCategory;
import cn.openea.perpartner.meily.web.entity.dto.CourseCategoryDTOFactory;
import cn.openea.perpartner.meily.web.entity.vo.CourseCategoryEditVo;
import cn.openea.perpartner.meily.web.mapper.CourseCategoryMapper;
import cn.openea.perpartner.meily.web.service.ICourseCategoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


@Service("courseCategoryService")
public class CourseCategoryServiceImpl extends ServiceImpl<CourseCategoryMapper, CourseCategory> implements ICourseCategoryService {

    @Override
    public List<CourseCategory> getListByParentId(Long parentId) {
        return baseMapper.selectList(new LambdaQueryWrapper<CourseCategory>().eq(CourseCategory::getParentId, parentId));
    }

    @CacheEvict(cacheNames = "queryCourseCategoryTreeList", key = "'queryCategoryTreeList'", cacheManager = "defaultRedisCacheManager")
    @Override
    public void edit(CourseCategoryEditVo editVo) {
        if (editVo.getId() == null) {
            throw new ServiceException("数据不存在");
        }
        CourseCategory oldCourseCategory = Optional.ofNullable(getById(editVo.getId()))
                .orElseThrow(() -> new ServiceException("数据不存在"));
        if (!editVo.getParentId().equals(oldCourseCategory.getParentId()) && editVo.getParentId() != 0) {
            // 说明更改的类目 需要判断类目是否存在
            Optional.ofNullable(getById(editVo.getParentId()))
                    .orElseThrow(() -> new ServiceException("该供应链父类不存在"));
        }
        // 判断同一个供应链下是否存在相同名称的数据
        if (existence(editVo.getName(), editVo.getParentId())) {
            throw new ServiceException(editVo.getName() + "已存在");
        }
        CourseCategory courseCategory = new CourseCategory();
        courseCategory.setId(editVo.getId());
        courseCategory.setParentId(editVo.getParentId());
        courseCategory.setName(editVo.getName());
        updateById(courseCategory);
    }

    @CacheEvict(cacheNames = "queryCourseCategoryTreeList", key = "'queryCategoryTreeList'", cacheManager = "defaultRedisCacheManager")
    @Override
    public void add(CourseCategoryEditVo editVo) {
        if (editVo.getParentId() != 0) {
            Optional.ofNullable(getById(editVo.getParentId()))
                    .orElseThrow(() -> new ServiceException("该分类所选择的父类别不存在"));
            // 判断同一个供应链下是否存在相同名称的数据
            if (existence(editVo.getName(), editVo.getParentId())) {
                throw new ServiceException(editVo.getName() + "已存在");
            }
        }
        CourseCategory courseCategory = new CourseCategory();
        courseCategory.setParentId(editVo.getParentId());
        courseCategory.setName(editVo.getName());
        baseMapper.insert(courseCategory);
    }

    @Override
    public boolean existence(String name, Long parentId) {
        return baseMapper.existenceDataByParentId(parentId, name) != null;
    }

    @Cacheable(cacheNames = "queryCourseCategoryTreeList", key = "#root.methodName", cacheManager = "defaultRedisCacheManager")
    @Override
    public List<CourseCategoryDTOFactory.CategoryTreeDTO> queryCategoryTreeList() {
        // 获取所有分类
        List<CourseCategory> courseCategories = baseMapper.selectList(null);
        return courseCategories.stream()
                .filter((category) -> category.getParentId() == 0)
                .map(item -> CourseCategoryDTOFactory.CategoryTreeDTO.builder()
                        .id(item.getId())
                        .parentId(item.getParentId())
                        .name(item.getName())
                        .checked(false)
                        .build())
                .peek(item -> {
                    item.setChildren(getChildren(item, courseCategories));
                }).collect(Collectors.toList());
    }

    private List<CourseCategoryDTOFactory.CategoryTreeDTO> getChildren(CourseCategoryDTOFactory.CategoryTreeDTO root, List<CourseCategory> courseCategories) {
        return courseCategories.stream()
                .filter(category -> category.getParentId().equals(root.getId()))
                .map(item -> CourseCategoryDTOFactory.CategoryTreeDTO.builder()
                        .id(item.getId())
                        .parentId(item.getParentId())
                        .name(item.getName())
                        .checked(false)
                        .build())
                .peek(categoryEntity -> categoryEntity.setChildren(getChildren(categoryEntity, courseCategories)))
                .collect(Collectors.toList());
    }
}